package com.example.sprintboot.service;

import com.example.sprintboot.common.WeChatApiUtil;
import com.example.sprintboot.dto.SendMessage;
import com.example.sprintboot.dto.WeChatAccessTokenResponse;
import com.example.sprintboot.entity.WeChatToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * 微信API调用服务
 * 演示如何调用微信第三方API
 * 
 * ============================================
 * RestTemplate 发送请求的详细流程：
 * ============================================
 * 
 * 1. 【配置阶段】RestTemplateConfig 创建 RestTemplate Bean
 *    - 创建 RestTemplate 实例
 *    - 设置 ClientHttpRequestFactory（请求工厂）
 *    - 配置超时时间（连接超时5秒，读取超时10秒）
 * 
 * 2. 【注入阶段】通过 @Autowired 注入到 Service
 *    - Spring 容器自动注入配置好的 RestTemplate
 * 
 * 3. 【请求构建阶段】构建HTTP请求
 *    - 使用 UriComponentsBuilder 构建完整URL（包含查询参数）
 *    - 创建 HttpEntity（包含请求头、请求体）
 *    - 指定 HTTP 方法（GET、POST、PUT、DELETE等）
 * 
 * 4. 【请求发送阶段】调用 restTemplate.exchange()
 *    RestTemplate 内部执行流程：
 *    a) 解析URL，提取协议、主机、端口、路径等信息
 *    b) 通过 ClientHttpRequestFactory 创建 ClientHttpRequest
 *    c) 设置请求方法（GET/POST等）
 *    d) 设置请求头（Content-Type、Authorization等）
 *    e) 如果有请求体，写入请求体（JSON/XML等）
 *    f) 建立TCP连接（如果是HTTPS，还会建立SSL连接）
 *    g) 发送HTTP请求到目标服务器
 *    h) 等待服务器响应
 *    i) 读取响应头
 *    j) 读取响应体
 *    k) 关闭连接
 * 
 * 5. 【响应处理阶段】处理HTTP响应
 *    - ResponseEntity 包含：状态码、响应头、响应体
 *    - 使用 ObjectMapper 将JSON字符串转换为Java对象
 * 
 * ============================================
 * 底层实现原理：
 * ============================================
 * 
 * RestTemplate 底层使用 Java 的 HttpURLConnection 或 Apache HttpClient
 * 
 * 1. SimpleClientHttpRequestFactory（默认）
 *    - 使用 Java 标准库的 HttpURLConnection
 *    - 适合简单的HTTP请求
 * 
 * 2. HttpComponentsClientHttpRequestFactory（可选）
 *    - 使用 Apache HttpClient
 *    - 功能更强大，支持连接池、重试等高级特性
 * 
 * ============================================
 * 实际发送的HTTP请求示例：
 * ============================================
 * 
 * GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxx&secret=xxx HTTP/1.1
 * Host: api.weixin.qq.com
 * Connection: keep-alive
 * User-Agent: Java/17.0.x
 * Accept: text/html, image/gif, image/jpeg, *; q=.2, */

@Service
public class WeChatService {

    @Autowired
    private WeChatApiUtil weChatApiUtil;
    
    @Autowired
    private WeChatTokenService weChatTokenService;
    
    @Value("${wechat.default.appid}")
    private String defaultAppid;
    
    @Value("${wechat.default.secret}")
    private String defaultSecret;




    /**
     * 发送微信订阅消息
     * 
     * @param templateId 模板ID
     * @param touser 接收者openid
     * @param data 模板数据
     * @return 发送结果
     */
    public SendMessage sendMessage(String templateId, String touser, Object data) {
        return sendMessage(templateId, touser, data, "formal");
    }

    /**
     * 发送微信订阅消息（可指定小程序状态）
     * 
     * @param templateId 模板ID
     * @param touser 接收者openid
     * @param data 模板数据
     * @param miniprogramState 小程序状态：developer(开发版)、trial(体验版)、formal(正式版)
     * @return 发送结果
     */
    public SendMessage sendMessage(String templateId, String touser, Object data, String miniprogramState) {
        WeChatAccessTokenResponse tokenResponse = getAccessToken();
        
        // 检查token是否获取成功
        if (!tokenResponse.isSuccess()) {
            SendMessage errorResult = new SendMessage();
            errorResult.setTemplateId(templateId);
            errorResult.setTouser(touser);
            errorResult.setData("获取access_token失败: " + tokenResponse.getErrmsg());
            return errorResult;
        }
        
        String accessToken = tokenResponse.getAccessToken();
        
        // 使用封装的微信API工具发送消息
        WeChatApiUtil.WeChatSendMessageResponse apiResponse = weChatApiUtil.sendSubscribeMessage(
                accessToken, templateId, touser, data, miniprogramState
        );
        
        // 转换为业务响应对象
        SendMessage result = new SendMessage();
        result.setTemplateId(templateId);
        result.setTouser(touser);
        
        // 详细的响应处理
        System.out.println("=== 微信API响应处理 ===");
        System.out.println("isSuccess: " + apiResponse.isSuccess());
        System.out.println("errcode: " + apiResponse.getErrcode());
        System.out.println("errmsg: " + apiResponse.getErrmsg());
        System.out.println("msgid: " + apiResponse.getMsgid());
        System.out.println("rawResponse: " + apiResponse.getRawResponse());
        System.out.println("========================");
        
        if (apiResponse.isSuccess()) {
            result.setData("✅ 发送成功，消息ID: " + apiResponse.getMsgid());
        } else {
            String errorMsg = String.format("❌ 发送失败，错误码: %d, 错误信息: %s", 
                    apiResponse.getErrcode(), apiResponse.getErrmsg());
            result.setData(errorMsg);
            
            // 特殊处理412错误
            if (apiResponse.getErrcode() != null && apiResponse.getErrcode() == 412) {
                result.setData("❌ 412错误：用户未订阅该模板消息或订阅已过期。请在小程序中重新订阅后立即测试。");
            }
        }
        
        return result;
    }
    
     /**
      * 发送微信订阅消息（简化版本，只需要templateId）
      * 
      * @param templateId 模板ID
      * @return 发送结果
      */
     public SendMessage sendMessage(String templateId) {
         // 使用默认的测试用户和数据
         String defaultTouser = "owXcB7hyKl73lGmOxn797nN713ik"; // 这里应该是实际的用户openid
         
         // 创建多种可能的模板数据格式，增加成功率
         Object defaultData = createTestTemplateData();
         
         return sendMessage(templateId, defaultTouser, defaultData);
     }
     
     /**
      * 创建测试用的模板数据（基于你的UniApp成功案例）
      * 模板ID: zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8
      */
     private Object createTestTemplateData() {
         return new java.util.HashMap<String, Object>() {{
             // 根据你的UniApp成功案例的字段格式
             put("thing1", new java.util.HashMap<String, String>() {{
                 put("value", "测试学员"); // 用户名称
             }});
             put("thing2", new java.util.HashMap<String, String>() {{
                 put("value", "Spring Boot课程"); // 预约项目
             }});
             put("time3", new java.util.HashMap<String, String>() {{
                 put("value", java.time.LocalDateTime.now().format(
                     java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                 )); // 预约时间
             }});
             put("thing4", new java.util.HashMap<String, String>() {{
                 put("value", "请按时参加课程学习，如有疑问请联系客服"); // 温馨提示
             }});
             put("thing10", new java.util.HashMap<String, String>() {{
                 put("value", "专业讲师"); // 预约门店/讲师
             }});
         }};
     }
     
     /**
      * 调试用：发送简单的订阅消息（最小化数据）
      * 
      * @param templateId 模板ID
      * @return 发送结果
      */
     public SendMessage sendSimpleMessage(String templateId) {
         String defaultTouser = "owXcB7hyKl73lGmOxn797nN713ik";
         
         // 最简单的数据格式，只包含一个字段
         Object simpleData = new java.util.HashMap<String, Object>() {{
             put("thing1", new java.util.HashMap<String, String>() {{
                 put("value", "测试");
             }});
         }};
         
         return sendMessage(templateId, defaultTouser, simpleData);
     }
     
     /**
      * 调试用：发送订阅消息（可自定义小程序状态）
      * 
      * @param templateId 模板ID
      * @param miniprogramState 小程序状态：developer(开发版)、trial(体验版)、formal(正式版)
      * @return 发送结果
      */
     public SendMessage sendMessageWithState(String templateId, String miniprogramState) {
         String touser = "owXcB7hyKl73lGmOxn797nN713ik";
         
         // 构建测试数据
         Object testData = new java.util.HashMap<String, Object>() {{
             put("thing1", new java.util.HashMap<String, String>() {{
                 put("value", "状态测试:" + miniprogramState);
             }});
         }};
         
         System.out.println("=== 调试：不同状态测试 ===");
         System.out.println("小程序状态: " + miniprogramState);
         System.out.println("========================");
         
         // 使用重构后的sendMessage方法
         return sendMessage(templateId, touser, testData, miniprogramState);
     }
     
     /**
      * 使用你的实际模板ID发送订阅消息（推荐使用）
      * 模板ID: zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8
      * 
      * @return 发送结果
      */
     public SendMessage sendRealTemplateMessage() {
         String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8"; // 你的实际模板ID
         String touser = "owXcB7hyKl73lGmOxn797nN713ik"; // 你的实际用户openid
         
         // 使用与UniApp完全相同的数据格式
         Object messageData = new java.util.HashMap<String, Object>() {{
             put("thing1", new java.util.HashMap<String, String>() {{
                 put("value", "测试学员"); // 用户名称
             }});
             put("thing2", new java.util.HashMap<String, String>() {{
                 put("value", "Spring Boot API测试课程"); // 预约项目
             }});
             put("time3", new java.util.HashMap<String, String>() {{
                 put("value", java.time.LocalDateTime.now().format(
                     java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                 )); // 预约时间
             }});
             put("thing4", new java.util.HashMap<String, String>() {{
                 put("value", "请按时参加课程学习，如有疑问请联系客服"); // 温馨提示
             }});
             put("thing10", new java.util.HashMap<String, String>() {{
                 put("value", "Spring Boot专业讲师"); // 预约门店/讲师
             }});
         }};
         
         return sendMessage(templateId, touser, messageData);
     }
     
     /**
      * 发送课程预约通知（业务方法）
      * 
      * @param userName 用户名称
      * @param courseName 课程名称
      * @param courseTime 课程时间
      * @param teacherName 讲师名称
      * @param tips 温馨提示
      * @return 发送结果
      */
     public SendMessage sendCourseBookingNotification(String userName, String courseName, 
             String courseTime, String teacherName, String tips) {
         String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8";
         String touser = "owXcB7hyKl73lGmOxn797nN713ik";
         
         Object messageData = new java.util.HashMap<String, Object>() {{
             put("thing1", new java.util.HashMap<String, String>() {{
                 put("value", userName != null ? userName : "学员");
             }});
             put("thing2", new java.util.HashMap<String, String>() {{
                 put("value", courseName != null ? courseName : "课程");
             }});
             put("time3", new java.util.HashMap<String, String>() {{
                 put("value", courseTime != null ? courseTime : 
                     java.time.LocalDateTime.now().format(
                         java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                     ));
             }});
             put("thing4", new java.util.HashMap<String, String>() {{
                 put("value", tips != null ? tips : "请按时参加课程学习，如有疑问请联系客服");
             }});
             put("thing10", new java.util.HashMap<String, String>() {{
                 put("value", teacherName != null ? teacherName : "专业讲师");
             }});
         }};
         
         return sendMessage(templateId, touser, messageData);
    }







        /**
     * 智能获取 access_token（推荐使用）
     * 
     * 流程：
     * 1. 先从数据库查询是否有有效的token（未过期）
     * 2. 如果有有效的token，直接返回
     * 3. 如果没有或已过期，调用微信API获取新token并保存到数据库
     * 
     * 优点：减少对微信API的调用次数，提高性能
     * 
     * @param appid 微信AppID
     * @param secret 微信AppSecret
     * @return access_token响应对象
     */
        public WeChatAccessTokenResponse getAccessTokenSmart(String appid, String secret) {
            // 步骤1：先从数据库查询是否有有效的token
            WeChatToken existingToken = weChatTokenService.getValidToken(appid);
            
            if (existingToken != null && !existingToken.isExpired()) {
                // 数据库中有有效的token，直接返回
                WeChatAccessTokenResponse response = new WeChatAccessTokenResponse();
                response.setAccessToken(existingToken.getAccessToken());
                response.setExpiresIn(existingToken.getExpiresIn());
                return response;
            }
            
            // 步骤2：数据库中没有有效的token，调用微信API获取新token
            // getAccessToken() 方法内部会自动保存到数据库
            return getAccessToken(appid, secret);
        }
        
    /**
     * 智能获取微信 access_token（使用默认配置）
     * 
     * 先从数据库查询有效的token，如果没有或已过期，才调用微信API获取新的token
     * 
     * 优点：减少对微信API的调用次数，提高性能
     * 
     * @return access_token响应对象
     */
    public WeChatAccessTokenResponse getAccessTokenSmart() {
        return getAccessTokenSmart(defaultAppid, defaultSecret);
        }

    /**
     * 获取微信 access_token
     * 
     * 微信官方文档：https://developers.weixin.qq.com/doc/oplatform/en/Website_App/WeChat_Login/Wechat_Login.html
     * 
     * API地址：GET https://api.weixin.qq.com/cgi-bin/token
     * 参数：
     *   - grant_type: 固定值 "client_credential"
     *   - appid: 第三方用户唯一凭证
     *   - secret: 第三方用户唯一凭证密钥
     * 
     * @param appid 微信AppID
     * @param secret 微信AppSecret
     * @return access_token响应对象
     */
    public WeChatAccessTokenResponse getAccessToken(String appid, String secret) {
        // 使用封装的微信API工具获取token
        WeChatAccessTokenResponse tokenResponse = weChatApiUtil.getAccessToken(appid, secret);

        // 如果获取成功，将token保存到数据库
        if (tokenResponse.isSuccess() && tokenResponse.getAccessToken() != null) {
            weChatTokenService.saveOrUpdateToken(
                    appid,
                    tokenResponse.getAccessToken(),
                    tokenResponse.getExpiresIn()
            );
        }

        return tokenResponse;
    }
    
    /**
     * 获取微信 access_token（使用默认配置）
     * 
     * 直接调用微信API获取新的access_token，并保存到数据库
     * 
     * @return access_token响应对象
     */
    public WeChatAccessTokenResponse getAccessToken() {
        return getAccessToken(defaultAppid, defaultSecret);
    }

    /**
     * 获取微信 access_token（使用配置文件中的appid和secret）
     * 
     * 注意：需要在 application.yml 中配置：
     * wechat:
     *   appid: YOUR_APPID
     *   secret: YOUR_SECRET
     * 
     * @param appid 从配置文件读取的AppID（可选，如果传null则从配置文件读取）
     * @param secret 从配置文件读取的Secret（可选，如果传null则从配置文件读取）
     * @return access_token响应对象
     */
    public WeChatAccessTokenResponse getAccessTokenFromConfig(String appid, String secret) {
        // 如果参数为空，可以从配置文件中读取
        // 这里简化处理，直接使用传入的参数
        if (appid == null || secret == null) {
            WeChatAccessTokenResponse errorResponse = new WeChatAccessTokenResponse();
            errorResponse.setErrcode(-1);
            errorResponse.setErrmsg("AppID和Secret不能为空");
            return errorResponse;
        }
        return getAccessToken(appid, secret);
    }
    
    /**
     * 调试方法：尝试发送到不同的openid（如果你有多个测试用户）
     */
    public SendMessage testDifferentUsers() {
        String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8";
        
        // 你可以添加其他测试用户的openid
        String[] testUsers = {
            "owXcB7hyKl73lGmOxn797nN713ik", // 你当前的用户
            // "另一个测试用户的openid" // 如果有的话
        };
        
        Object messageData = new java.util.HashMap<String, Object>() {{
            put("thing1", new java.util.HashMap<String, String>() {{
                put("value", "多用户测试");
            }});
            put("thing2", new java.util.HashMap<String, String>() {{
                put("value", "用户测试课程");
            }});
            put("time3", new java.util.HashMap<String, String>() {{
                put("value", java.time.LocalDateTime.now().format(
                    java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                ));
            }});
            put("thing4", new java.util.HashMap<String, String>() {{
                put("value", "这是多用户测试消息");
            }});
            put("thing10", new java.util.HashMap<String, String>() {{
                put("value", "测试讲师");
            }});
        }};
        
        // 只测试第一个用户
        return sendMessage(templateId, testUsers[0], messageData);
    }
    
    /**
     * 尝试使用最小化的请求体（排除可选字段）
     */
    public SendMessage sendMinimalMessage() {
        String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8";
        String touser = "owXcB7hyKl73lGmOxn797nN713ik";
        
        // 只包含一个最简单的字段
        Object minimalData = new java.util.HashMap<String, Object>() {{
            put("thing1", new java.util.HashMap<String, String>() {{
                put("value", "最简测试");
            }});
        }};
        
        System.out.println("=== 最小化请求测试 ===");
        System.out.println("====================");
        
        // 使用null作为小程序状态，让工具类不添加可选字段
        return sendMessage(templateId, touser, minimalData, null);
    }
    
    /**
     * 诊断订阅消息问题的工具方法
     * 提供详细的问题分析和解决建议
     */
    public java.util.Map<String, Object> diagnoseSubscriptionMessage() {
        java.util.Map<String, Object> diagnosis = new java.util.HashMap<>();
        
        // 基本信息
        diagnosis.put("templateId", "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8");
        diagnosis.put("openid", "owXcB7hyKl73lGmOxn797nN713ik");
        diagnosis.put("timestamp", java.time.LocalDateTime.now().toString());
        
        // 检查access_token
        WeChatAccessTokenResponse tokenResponse = getAccessToken();
        diagnosis.put("accessTokenValid", tokenResponse.isSuccess());
        if (tokenResponse.isSuccess()) {
            diagnosis.put("accessToken", tokenResponse.getAccessToken().substring(0, 20) + "...");
        } else {
            diagnosis.put("accessTokenError", tokenResponse.getErrmsg());
        }
        
        // 412错误的可能原因分析
        java.util.List<String> possibleCauses = new java.util.ArrayList<>();
        possibleCauses.add("1. 用户未订阅该模板消息");
        possibleCauses.add("2. 用户订阅已过期（通常24小时后过期）");
        possibleCauses.add("3. 模板在微信公众平台中状态异常（未审核通过/被禁用）");
        possibleCauses.add("4. 小程序环境问题（可能需要使用开发版）");
        possibleCauses.add("5. 用户在小程序中关闭了订阅消息权限");
        
        diagnosis.put("possibleCauses", possibleCauses);
        
        // 解决方案
        java.util.List<String> solutions = new java.util.ArrayList<>();
        solutions.add("1. 确保用户在小程序中通过 uni.requestSubscribeMessage() 订阅了该模板");
        solutions.add("2. 检查订阅时间，确保在24小时内");
        solutions.add("3. 登录微信公众平台检查模板状态");
        solutions.add("4. 尝试使用开发版小程序进行测试");
        solutions.add("5. 让用户重新授权订阅消息");
        
        diagnosis.put("solutions", solutions);
        
        // 测试建议
        java.util.List<String> testSuggestions = new java.util.ArrayList<>();
        testSuggestions.add("1. 在小程序中先调用订阅接口：uni.requestSubscribeMessage({tmplIds: ['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8']})");
        testSuggestions.add("2. 订阅成功后立即测试发送消息");
        testSuggestions.add("3. 使用开发版小程序进行测试");
        testSuggestions.add("4. 检查微信开发者工具的控制台是否有相关错误信息");
        
        diagnosis.put("testSuggestions", testSuggestions);
        
        return diagnosis;
    }
    
    /**
     * 创建用于测试的订阅消息前端代码
     * 返回可以直接在小程序中使用的代码示例
     */
    public java.util.Map<String, Object> generateTestCode() {
        java.util.Map<String, Object> codeExamples = new java.util.HashMap<>();
        
        // 小程序订阅代码
        String subscribeCode = """
            // 在小程序中调用此方法来订阅消息
            async subscribeMessage() {
              try {
                const result = await uni.requestSubscribeMessage({
                  tmplIds: ['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8']
                });
                
                console.log('订阅结果:', result);
                
                if (result['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8'] === 'accept') {
                  console.log('用户同意订阅');
                  // 立即测试发送消息
                  this.testSendMessage();
                } else {
                  console.log('用户拒绝订阅');
                  uni.showToast({
                    title: '需要订阅才能接收消息',
                    icon: 'none'
                  });
                }
              } catch (error) {
                console.error('订阅失败:', error);
              }
            },
            
            // 测试发送消息
            testSendMessage() {
              uni.request({
                url: 'http://localhost:9090/wechat/sendRealMessage',
                method: 'GET',
                success: (res) => {
                  console.log('发送结果:', res);
                  uni.showToast({
                    title: res.data.code === '200' ? '发送成功' : '发送失败',
                    icon: res.data.code === '200' ? 'success' : 'none'
                  });
                },
                fail: (error) => {
                  console.error('请求失败:', error);
                }
              });
            }
            """;
        
        codeExamples.put("subscribeCode", subscribeCode);
        
        // 完整的测试页面代码
        String fullPageCode = """
            <template>
              <view class="container">
                <button @click="subscribeMessage" type="primary">1. 先订阅消息</button>
                <button @click="testSendMessage" type="default" style="margin-top: 20rpx;">2. 测试发送消息</button>
                <view class="tips">
                  <text>使用步骤：</text>
                  <text>1. 点击"先订阅消息"按钮</text>
                  <text>2. 在弹出的授权框中点击"允许"</text>
                  <text>3. 点击"测试发送消息"按钮</text>
                  <text>4. 查看小程序是否收到订阅消息</text>
                </view>
              </view>
            </template>
            
            <script>
            export default {
              methods: {
                async subscribeMessage() {
                  try {
                    const result = await uni.requestSubscribeMessage({
                      tmplIds: ['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8']
                    });
                    
                    console.log('订阅结果:', result);
                    
                    if (result['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8'] === 'accept') {
                      uni.showToast({
                        title: '订阅成功',
                        icon: 'success'
                      });
                    } else {
                      uni.showToast({
                        title: '需要允许订阅才能接收消息',
                        icon: 'none'
                      });
                    }
                  } catch (error) {
                    console.error('订阅失败:', error);
                    uni.showToast({
                      title: '订阅失败',
                      icon: 'none'
                    });
                  }
                },
                
                testSendMessage() {
                  uni.request({
                    url: 'http://localhost:9090/wechat/sendRealMessage',
                    method: 'GET',
                    success: (res) => {
                      console.log('发送结果:', res);
                      if (res.data.code === '200') {
                        uni.showToast({
                          title: '发送成功，请查看消息',
                          icon: 'success'
                        });
                      } else {
                        uni.showToast({
                          title: '发送失败: ' + res.data.message,
                          icon: 'none'
                        });
                      }
                    },
                    fail: (error) => {
                      console.error('请求失败:', error);
                      uni.showToast({
                        title: '网络请求失败',
                        icon: 'none'
                      });
                    }
                  });
                }
              }
            }
            </script>
            
            <style>
            .container {
              padding: 40rpx;
            }
            .tips {
              margin-top: 40rpx;
              padding: 20rpx;
              background-color: #f0f0f0;
              border-radius: 10rpx;
            }
            .tips text {
              display: block;
              margin-bottom: 10rpx;
              font-size: 28rpx;
              color: #666;
            }
            </style>
            """;
        
        codeExamples.put("fullPageCode", fullPageCode);
        
        return codeExamples;
    }
    
    /**
     * 尝试不同的字段组合来找出正确的模板格式
     */
    public java.util.Map<String, Object> testDifferentFieldCombinations() {
        String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8";
        String touser = "owXcB7hyKl73lGmOxn797nN713ik";
        java.util.Map<String, Object> results = new java.util.HashMap<>();
        
        // 测试1: 只有thing1
        java.util.Map<String, Object> test1Data = new java.util.HashMap<>();
        test1Data.put("thing1", new java.util.HashMap<String, String>() {{
            put("value", "测试1");
        }});
        
        // 测试2: 只有thing2  
        java.util.Map<String, Object> test2Data = new java.util.HashMap<>();
        test2Data.put("thing2", new java.util.HashMap<String, String>() {{
            put("value", "测试2");
        }});
        
        // 测试3: 只有time3
        java.util.Map<String, Object> test3Data = new java.util.HashMap<>();
        test3Data.put("time3", new java.util.HashMap<String, String>() {{
            put("value", "2025-11-22 21:45:00");
        }});
        
        // 测试4: thing1 + thing2
        java.util.Map<String, Object> test4Data = new java.util.HashMap<>();
        test4Data.put("thing1", new java.util.HashMap<String, String>() {{
            put("value", "用户名");
        }});
        test4Data.put("thing2", new java.util.HashMap<String, String>() {{
            put("value", "课程名");
        }});
        
        // 测试5: 尝试其他可能的字段名
        java.util.Map<String, Object> test5Data = new java.util.HashMap<>();
        test5Data.put("name1", new java.util.HashMap<String, String>() {{
            put("value", "测试姓名");
        }});
        test5Data.put("thing2", new java.util.HashMap<String, String>() {{
            put("value", "测试内容");
        }});
        
        @SuppressWarnings("unchecked")
        java.util.Map<String, Object>[] testDataArray = new java.util.Map[]{
            test1Data, test2Data, test3Data, test4Data, test5Data
        };
        
        String[] testNames = {"只有thing1", "只有thing2", "只有time3", "thing1+thing2", "name1+thing2"};
        
        for (int i = 0; i < testDataArray.length; i++) {
            try {
                SendMessage result = sendMessage(templateId, touser, testDataArray[i]);
                results.put(testNames[i], result.getData());
            } catch (Exception e) {
                results.put(testNames[i], "异常: " + e.getMessage());
            }
        }
        
        return results;
    }
    
    /**
     * 验证AppID和模板ID的匹配性
     */
    public java.util.Map<String, Object> validateAppIdAndTemplate() {
        java.util.Map<String, Object> validation = new java.util.HashMap<>();
        
        // 当前配置信息
        validation.put("currentAppId", defaultAppid);
        validation.put("templateId", "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8");
        validation.put("openid", "owXcB7hyKl73lGmOxn797nN713ik");
        
        // 检查access_token
        WeChatAccessTokenResponse tokenResponse = getAccessToken();
        validation.put("accessTokenStatus", tokenResponse.isSuccess() ? "正常" : "失败");
        
        if (tokenResponse.isSuccess()) {
            validation.put("accessTokenPrefix", tokenResponse.getAccessToken().substring(0, 10) + "...");
        }
        
        // 可能的问题
        java.util.List<String> possibleIssues = new java.util.ArrayList<>();
        possibleIssues.add("1. 模板字段名称不匹配实际模板");
        possibleIssues.add("2. 小程序AppID与后端配置的AppID不一致");
        possibleIssues.add("3. 模板状态异常（被禁用或审核中）");
        possibleIssues.add("4. OpenID不属于该AppID的用户");
        possibleIssues.add("5. 模板数据格式不符合微信要求");
        
        validation.put("possibleIssues", possibleIssues);
        
        // 建议的验证步骤
        java.util.List<String> verificationSteps = new java.util.ArrayList<>();
        verificationSteps.add("1. 登录微信公众平台，检查模板详细信息");
        verificationSteps.add("2. 确认小程序AppID与后端配置一致");
        verificationSteps.add("3. 查看模板的具体字段要求");
        verificationSteps.add("4. 尝试使用微信开发者工具的云调试功能");
        verificationSteps.add("5. 检查是否有字符长度限制");
        
        validation.put("verificationSteps", verificationSteps);
        
        return validation;
    }
    
    /**
     * 尝试发送到微信测试号（如果有的话）
     */
    public SendMessage sendToTestAccount() {
        SendMessage result = new SendMessage();
        result.setData("测试号功能需要配置具体的测试号信息");
        
        // 如果配置了测试号信息，可以取消注释下面的代码
        /*
        try {
            WeChatAccessTokenResponse tokenResponse = getAccessToken(testAppId, testSecret);
            if (tokenResponse.isSuccess()) {
                Object testData = new java.util.HashMap<String, Object>() {{
                    put("first", new java.util.HashMap<String, String>() {{
                        put("value", "测试消息");
                    }});
                    put("keyword1", new java.util.HashMap<String, String>() {{
                        put("value", "测试内容");
                    }});
                    put("remark", new java.util.HashMap<String, String>() {{
                        put("value", "这是测试");
                    }});
                }};
                
                return sendMessage(testTemplateId, testOpenId, testData);
            }
        } catch (Exception e) {
            result.setData("测试号发送失败: " + e.getMessage());
        }
        */
        
        return result;
    }
    
    /**
     * 验证AppID匹配性的专门方法
     * 基于模板信息确认的调试
     */
    public java.util.Map<String, Object> verifyAppIdMatch() {
        java.util.Map<String, Object> verification = new java.util.HashMap<>();
        
        // 当前配置
        verification.put("backendAppId", defaultAppid);
        verification.put("templateId", "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8");
        verification.put("openid", "owXcB7hyKl73lGmOxn797nN713ik");
        
        // 模板字段确认（基于截图）
        java.util.Map<String, String> templateFields = new java.util.HashMap<>();
        templateFields.put("thing1", "用户名称");
        templateFields.put("thing2", "预约项目");
        templateFields.put("time3", "预约时间");
        templateFields.put("thing4", "温馨提示");
        templateFields.put("thing10", "预约门店");
        verification.put("templateFields", templateFields);
        
        // 问题分析
        java.util.List<String> analysis = new java.util.ArrayList<>();
        analysis.add("✅ 用户已成功订阅模板");
        analysis.add("✅ 模板字段格式正确");
        analysis.add("✅ 模板ID正确");
        analysis.add("❌ 仍出现412错误");
        analysis.add("🔍 最可能原因：小程序AppID与后端AppID不匹配");
        
        verification.put("analysis", analysis);
        
        // 解决方案
        java.util.List<String> solutions = new java.util.ArrayList<>();
        solutions.add("1. 检查小程序的AppID是否为: " + defaultAppid);
        solutions.add("2. 确认订阅时使用的小程序与API调用的AppID一致");
        solutions.add("3. 检查OpenID是否属于正确的AppID");
        solutions.add("4. 尝试重新获取用户的OpenID");
        
        verification.put("solutions", solutions);
        
        // 测试建议
        java.util.List<String> testSteps = new java.util.ArrayList<>();
        testSteps.add("1. 在小程序中打印 wx.getAccountInfoSync().miniProgram.appId");
        testSteps.add("2. 确认打印的AppID与后端配置的 " + defaultAppid + " 一致");
        testSteps.add("3. 如果不一致，更新后端配置或使用正确的小程序");
        testSteps.add("4. 重新获取用户OpenID并测试");
        
        verification.put("testSteps", testSteps);
        
        return verification;
    }
    
    /**
     * 使用正确的模板字段格式发送消息（基于截图确认）
     */
    public SendMessage sendWithConfirmedTemplate() {
        String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8";
        String touser = "owXcB7hyKl73lGmOxn797nN713ik";
        
        // 使用确认的模板字段格式
        Object messageData = new java.util.HashMap<String, Object>() {{
            put("thing1", new java.util.HashMap<String, String>() {{
                put("value", "张三"); // 用户名称
            }});
            put("thing2", new java.util.HashMap<String, String>() {{
                put("value", "机修"); // 预约项目
            }});
            put("time3", new java.util.HashMap<String, String>() {{
                put("value", "2025-11-22 21:50:00"); // 预约时间
            }});
            put("thing4", new java.util.HashMap<String, String>() {{
                put("value", "请及时处理"); // 温馨提示
            }});
            put("thing10", new java.util.HashMap<String, String>() {{
                put("value", "某某门店"); // 预约门店
            }});
        }};
        
        return sendMessage(templateId, touser, messageData);
    }
    
    /**
     * 增强的调试方法：详细分析412错误
     */
    public SendMessage debugSubscriptionMessage() {
        String templateId = "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8";
        String touser = "owXcB7hyKl73lGmOxn797nN713ik";
        
        // 简化的数据格式
        Object debugData = new java.util.HashMap<String, Object>() {{
            put("thing1", new java.util.HashMap<String, String>() {{
                put("value", "调试测试");
            }});
        }};
        
        System.out.println("=== 详细调试信息 ===");
        System.out.println("==================");
        
        // 使用开发版进行调试
        SendMessage result = sendMessage(templateId, touser, debugData, "developer");
        
        // 如果发送失败，进行错误分析
        if (result.getData() != null && result.getData().toString().contains("发送失败")) {
            String errorAnalysis = analyzeError412(result.getData().toString());
            result.setData("412错误分析: " + errorAnalysis);
        }
        
        return result;
    }
    
    /**
     * 分析412错误的具体原因
     */
    private String analyzeError412(String responseBody) {
        StringBuilder analysis = new StringBuilder();
        analysis.append("412 PRECONDITION_FAILED 错误分析：\n");
        
        if (responseBody == null || responseBody.trim().isEmpty()) {
            analysis.append("- 响应体为空，这通常表示：\n");
            analysis.append("  1. 用户未订阅该模板消息\n");
            analysis.append("  2. 用户订阅已过期（超过24小时）\n");
            analysis.append("  3. 用户在小程序中拒绝了订阅权限\n");
            analysis.append("  4. OpenID与AppID不匹配\n");
        } else {
            analysis.append("- 响应体内容: ").append(responseBody).append("\n");
        }
        
        analysis.append("\n解决方案：\n");
        analysis.append("1. 在小程序中重新调用 uni.requestSubscribeMessage() 订阅\n");
        analysis.append("2. 确保订阅后24小时内发送消息\n");
        analysis.append("3. 检查小程序AppID与后端配置是否一致\n");
        analysis.append("4. 确认用户OpenID是否正确\n");
        
        return analysis.toString();
    }

    /**
     * 专门针对当前问题的诊断工具
     * 基于日志分析的精准诊断
     */
    public java.util.Map<String, Object> diagnoseCurrentIssue() {
        java.util.Map<String, Object> diagnosis = new java.util.HashMap<>();
        
        // 当前状态分析
        diagnosis.put("currentStatus", "412 PRECONDITION_FAILED + 空响应体");
        diagnosis.put("analysisTime", java.time.LocalDateTime.now().toString());
        
        // 基于日志的分析结果
        java.util.List<String> logAnalysis = new java.util.ArrayList<>();
        logAnalysis.add("✅ Access Token获取正常 - 每次请求都成功获取新token");
        logAnalysis.add("✅ 请求格式完全正确 - JSON结构和字段名称符合微信API规范");
        logAnalysis.add("✅ 模板ID正确 - zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8");
        logAnalysis.add("✅ OpenID格式正确 - owXcB7hyKl73lGmOxn797nN713ik");
        logAnalysis.add("❌ 412错误且响应体为空 - 这是订阅问题的典型特征");
        
        diagnosis.put("logAnalysis", logAnalysis);
        
        // 问题确诊
        java.util.List<String> confirmedIssues = new java.util.ArrayList<>();
        confirmedIssues.add("🎯 确诊：用户未订阅该模板消息（99%概率）");
        confirmedIssues.add("📱 需要在小程序中重新执行订阅操作");
        confirmedIssues.add("⏰ 订阅后必须在24小时内发送消息");
        confirmedIssues.add("🔄 每次订阅只能发送一次消息");
        
        diagnosis.put("confirmedIssues", confirmedIssues);
        
        // 立即解决方案
        java.util.List<String> immediateSolution = new java.util.ArrayList<>();
        immediateSolution.add("1️⃣ 在小程序中执行以下代码：");
        immediateSolution.add("   uni.requestSubscribeMessage({");
        immediateSolution.add("     tmplIds: ['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8']");
        immediateSolution.add("   })");
        immediateSolution.add("2️⃣ 用户点击\"允许\"授权订阅");
        immediateSolution.add("3️⃣ 订阅成功后立即调用发送接口测试");
        immediateSolution.add("4️⃣ 不要等待，必须立即测试！");
        
        diagnosis.put("immediateSolution", immediateSolution);
        
        return diagnosis;
    }

    /**
     * 全面的412错误诊断工具
     * 提供详细的问题分析和解决建议
     */
    public java.util.Map<String, Object> diagnose412Error() {
        java.util.Map<String, Object> diagnosis = new java.util.HashMap<>();
        
        // 基本配置信息
        diagnosis.put("currentAppId", defaultAppid);
        diagnosis.put("templateId", "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8");
        diagnosis.put("openid", "owXcB7hyKl73lGmOxn797nN713ik");
        diagnosis.put("timestamp", java.time.LocalDateTime.now().toString());
        
        // 检查access_token状态
        WeChatAccessTokenResponse tokenResponse = getAccessToken();
        diagnosis.put("accessTokenValid", tokenResponse.isSuccess());
        if (tokenResponse.isSuccess()) {
            diagnosis.put("accessTokenPrefix", tokenResponse.getAccessToken().substring(0, 20) + "...");
        } else {
            diagnosis.put("accessTokenError", tokenResponse.getErrmsg());
        }
        
        // 412错误的详细分析
        java.util.List<String> errorCauses = new java.util.ArrayList<>();
        errorCauses.add("🔍 主要原因分析：");
        errorCauses.add("1. 用户未订阅模板消息 - 最常见原因（90%的情况）");
        errorCauses.add("2. 用户订阅已过期 - 微信订阅消息24小时后自动过期");
        errorCauses.add("3. AppID不匹配 - 小程序AppID与后端配置不一致");
        errorCauses.add("4. OpenID错误 - 用户OpenID不属于当前AppID");
        errorCauses.add("5. 模板状态异常 - 模板被禁用或正在审核中");
        
        diagnosis.put("errorCauses", errorCauses);
        
        // 立即可执行的解决方案
        java.util.List<String> immediateSolutions = new java.util.ArrayList<>();
        immediateSolutions.add("🚀 立即执行的解决方案：");
        immediateSolutions.add("1. 在小程序中执行订阅操作：");
        immediateSolutions.add("   uni.requestSubscribeMessage({");
        immediateSolutions.add("     tmplIds: ['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8']");
        immediateSolutions.add("   })");
        immediateSolutions.add("2. 订阅成功后立即测试发送消息（不要等待）");
        immediateSolutions.add("3. 确保在24小时内发送消息");
        
        diagnosis.put("immediateSolutions", immediateSolutions);
        
        // 验证步骤
        java.util.List<String> verificationSteps = new java.util.ArrayList<>();
        verificationSteps.add("🔧 验证步骤：");
        verificationSteps.add("1. 检查小程序AppID：wx.getAccountInfoSync().miniProgram.appId");
        verificationSteps.add("2. 确认后端配置AppID：" + defaultAppid);
        verificationSteps.add("3. 验证用户OpenID是否正确");
        verificationSteps.add("4. 登录微信公众平台检查模板状态");
        
        diagnosis.put("verificationSteps", verificationSteps);
        
        // 测试建议
        java.util.List<String> testSuggestions = new java.util.ArrayList<>();
        testSuggestions.add("📋 测试建议：");
        testSuggestions.add("1. 使用开发版小程序进行测试");
        testSuggestions.add("2. 先测试获取用户OpenID是否正确");
        testSuggestions.add("3. 在订阅成功的回调中立即调用发送接口");
        testSuggestions.add("4. 检查微信开发者工具的网络面板");
        
        diagnosis.put("testSuggestions", testSuggestions);
        
        return diagnosis;
    }

    /**
     * 测试订阅消息的完整流程
     * 包含详细的步骤指导
     */
    public java.util.Map<String, Object> testSubscriptionFlow() {
        java.util.Map<String, Object> flowTest = new java.util.HashMap<>();
        
        // 第一步：检查基础配置
        flowTest.put("step1_config_check", java.util.Map.of(
            "appid", defaultAppid,
            "templateId", "zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8",
            "openid", "owXcB7hyKl73lGmOxn797nN713ik"
        ));
        
        // 第二步：检查access_token
        WeChatAccessTokenResponse tokenResponse = getAccessToken();
        flowTest.put("step2_token_check", java.util.Map.of(
            "success", tokenResponse.isSuccess(),
            "token_prefix", tokenResponse.isSuccess() ? 
                tokenResponse.getAccessToken().substring(0, 15) + "..." : "获取失败",
            "error", tokenResponse.isSuccess() ? "无" : tokenResponse.getErrmsg()
        ));
        
        // 第三步：小程序端订阅代码
        String subscriptionCode = """
            // 在小程序页面中添加此方法
            async subscribeAndTest() {
              try {
                console.log('开始订阅流程...');
                
                // 1. 请求订阅
                const result = await uni.requestSubscribeMessage({
                  tmplIds: ['zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8']
                });
                
                console.log('订阅结果:', result);
                
                // 2. 检查订阅状态
                const templateId = 'zvaRsziQ2U139jQdNUSSX8cCgyqHe_r5xIsuGo36wR8';
                if (result[templateId] === 'accept') {
                  console.log('✅ 用户同意订阅');
                  
                  // 3. 立即测试发送消息
                  uni.showLoading({ title: '发送中...' });
                  
                  uni.request({
                    url: 'http://localhost:9090/wechat/sendRealMessage',
                    method: 'GET',
                    success: (res) => {
                      uni.hideLoading();
                      console.log('📨 发送结果:', res);
                      
                      if (res.data.code === '200') {
                        uni.showToast({
                          title: '发送成功！',
                          icon: 'success'
                        });
                      } else {
                        uni.showToast({
                          title: '发送失败: ' + res.data.message,
                          icon: 'none',
                          duration: 3000
                        });
                      }
                    },
                    fail: (error) => {
                      uni.hideLoading();
                      console.error('❌ 请求失败:', error);
                      uni.showToast({
                        title: '网络请求失败',
                        icon: 'none'
                      });
                    }
                  });
                  
                } else if (result[templateId] === 'reject') {
                  console.log('❌ 用户拒绝订阅');
                  uni.showToast({
                    title: '需要允许订阅才能接收消息',
                    icon: 'none'
                  });
                } else {
                  console.log('⚠️ 订阅状态未知:', result[templateId]);
                }
                
              } catch (error) {
                console.error('💥 订阅失败:', error);
                uni.showToast({
                  title: '订阅失败: ' + error.message,
                  icon: 'none'
                });
              }
            }
            """;
        
        flowTest.put("step3_subscription_code", subscriptionCode);
        
        // 第四步：后端测试接口
        flowTest.put("step4_backend_test", java.util.Map.of(
            "test_url", "http://localhost:9090/wechat/sendRealMessage",
            "debug_url", "http://localhost:9090/wechat/diagnose412",
            "description", "订阅成功后立即调用测试接口"
        ));
        
        return flowTest;
    }

}
